/*
 * TransparentBitbltLayerMerger.cpp
 *
 *  Created on: 2010-9-20
 *      Author: wenjian
 */

#include "TransparentBitbltLayerMerger.h"
#include "Layer.h"
#include "DrawPage.h"

namespace Ed {

  TransparentBitbltLayerMerger::TransparentBitbltLayerMerger(DrawPage* page, COLORREF transparentColor):
    page(page), transparentColor(transparentColor) {

  }

  TransparentBitbltLayerMerger::~TransparentBitbltLayerMerger() {
    LayerBufferMap::iterator it = layerBufferMap.begin();
    for(; it != layerBufferMap.end(); it++){
      BufferItem* item = it->second;
      delete item->graphics;
      ReleaseDC(NULL, item->bufferDC);
      ReleaseDC(NULL, item->maskDC);
      delete item;
    }
  }


  /**
   * 返回BufferItem
   */
  TransparentBitbltLayerMerger::BufferItem* TransparentBitbltLayerMerger::getBufferItem(Layer* l){
    BufferItem* item = layerBufferMap[(long)l];
    if(!item){
      item = new BufferItem();
      layerBufferMap[(long)l] = item;

      //创建活动缓冲DC
      HDC hostDC = page->getPageHDC();
      item->bufferDC = CreateCompatibleDC(hostDC);
      HBITMAP bmp = CreateCompatibleBitmap( hostDC, (int)l->width(), (int)l->height());
      SelectObject( item->bufferDC, bmp );
      DeleteObject( bmp );

      //创建MaskDC
      item->maskDC = CreateCompatibleDC(hostDC);
      HBITMAP bmpMask = CreateBitmap((int)l->width(), (int)l->height(), 1, 1, NULL);
      SelectObject(item->maskDC, bmpMask );
      DeleteObject( bmpMask );

      //生成Graphics
      item->graphics =  new Gdiplus::Graphics(item->bufferDC);
      item->graphics->SetPageUnit(Gdiplus::UnitPixel);
      item->graphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
      item->graphics->SetTextRenderingHint(Gdiplus::TextRenderingHintClearTypeGridFit);

      //设置透明颜色
      SetBkColor(item->bufferDC, transparentColor);

      //清屏
      item->graphics->Clear(l->getBackground());
    }
    return item;
  }


  bool TransparentBitbltLayerMerger::merge(){
    HDC hostDC = page->getPageHDC();
    const std::vector<Layer*>* layers = (const std::vector<Layer*>*)page->getLayers();
    std::vector<Layer*>::const_iterator it = layers->begin();
    for(; it !=layers->end(); it++){
      Layer* layer = *it;
      BufferItem* item = getBufferItem(layer);
      layer->draw(item->graphics);
      BitBlt(item->maskDC, 0, 0, (int)layer->width(), (int)layer->height(), item->bufferDC, 0, 0, SRCCOPY);
      BitBlt(hostDC, (int)layer->x(), (int)layer->y(), (int)layer->width(), (int)layer->height(), item->bufferDC, 0, 0, SRCINVERT);
      BitBlt(hostDC, (int)layer->x(), (int)layer->y(), (int)layer->width(), (int)layer->height(), item->maskDC, 0, 0, SRCAND);
      BitBlt(hostDC, (int)layer->x(), (int)layer->y(), (int)layer->width(), (int)layer->height(), item->bufferDC, 0, 0, SRCINVERT);
    }
    return true;
  }

}
